<template>
  <!-- 登录界面 与 注册界面 结合后界面，未完成：输入验证，验证码， 提交 -->
  <div>
    <el-dialog :title="state.name !== LOGIN_STR ? '注册' : '登录'" v-model="state.visible">
      <el-form :model="form" status-icon ref="formRef" :rules="rules">
        <el-form-item label="用户名" prop="username">
          <el-input v-model="form.username" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="密码" prop="password">
          <el-input show-password class="password" v-model="form.password" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item v-show="state.name !== LOGIN_STR" label="确认密码" prop="rePassword">
          <el-input show-password class="rePassword" v-model="form.rePassword" autocomplete="off"></el-input>
        </el-form-item>
        <el-form-item label="验证码" prop="vCode">
          <el-input class="vCodeInput" v-model="form.vCode" autocomplete="off"></el-input>
          <VerifyCode class="vCodeImg" ref="verifyRef" />
       </el-form-item>
      </el-form>
        <template #footer>
          <span class="dialog-footer">
            <el-button @click="cancel">取 消</el-button>
            <el-button type="primary" @click="submit()">确 定</el-button>
            <el-button @click="resetForm()">重置</el-button>
          </span>
        </template>
    </el-dialog>
   </div>
</template>

<script lang="ts">
import { ref, reactive, defineComponent, onMounted, onBeforeUnmount, watch } from "vue"
import { validateUsername, validatePassword, validateRePassword } from "@/api/validate/userValidate"
import { userLogin, userRegister } from '@/api/axios/user'
import { CODE_KEY, CODE_SUCCESS, CODE_FAIL } from '@/api/params'
import { ElMessage } from 'element-plus'
import { useStore } from 'vuex'
// import { UserInfo } from "../store"
import VerifyCode from "@c/VerifyCode.vue"
import { Rules } from "async-validator/dist-types"
import { useRoute, useRouter } from "vue-router"

export default defineComponent ({
  props: {
    state: {
      name: String,
      visible: Boolean,
    }
  },
  components: {
    VerifyCode
  },
  setup (props) {
    
    const route = useRoute()
    const router = useRouter()
    const LOGIN_STR = "login"
    const REGISTER_STR = "register"
    
    const store = useStore()
    
    // 点击取消
    const cancel = () => {
      props.state.visible = false
    }
    
    const formRef = ref('')
    
    const form = reactive ({
      username: '',
      password: '',
      rePassword: '',
      vCode: '',
    })
    
    // 验证码
    const verifyRef = ref(undefined)

    const validateVCode = (rule: Rules, value: any, callback: (error: string | string[] | void) => void) : void => {
      console.log(value.toLowerCase() === verifyRef.value.imgCode.toLowerCase())
      if(value.length != 4) {
        callback(new Error("验证码格式错误"))
      } else if(value.toLowerCase() === verifyRef.value.imgCode.toLowerCase()) {
        callback();
      } else {
        console.log(verifyRef)
        // 刷新验证码
        verifyRef.value.handleDraw();
        callback(new Error("验证码错误"))
      }
    }
    
    // 取消对话框后刷新验证码，（因为如果是点开刷新，没点开前验证码还没加载 verifyRef 为 undefined ，不能调用其方法刷新)
    watch(() => props.state.visible, (newValue, oldValue) => {
      if(newValue === false && oldValue === true) {
        verifyRef.value.handleDraw();
      }
    })

    // 验证规则
    const rules = reactive({
      // 对应 prop 里名字
      username: [
        { validator: validateUsername, trigger: 'blur' }
      ],
      password: [
        { validator: validatePassword, trigger: 'blur' }
      ],
      rePassword: [
        { validator: validateRePassword, trigger: 'blur' }
      ],
      vCode: [
        { validator: validateVCode, trigger: "blur"}
      ]
    })
    
    // 提交信息
    const submit = () => {
      formRef.value.validate((valid) => {
        // 输入有效
        if(valid) {
          // 登录状态
          if(props.state.name === 'login') {
            // 登录，传参用户名与密码
            // 这里 form 需满足 user.ts 里的 interface User {username: string, password: string}
            // 否则单独传入参数: {username: [username], passowrd: [password]}
            userLogin(form).then(res => {
              // 如果 response 存在并且返回码 为成功，判断存在是为了 如果 访问后端失败 404 不会显示登录成功
              if(res && res.data[CODE_KEY] === CODE_SUCCESS) {
                // 这里 form 需满足 store 里的 type UserInfo = {username: string}
                store.commit('setUserInfo', form);
                ElMessage.success("登录成功");
                props.state.visible = false;
                // 登录成功，重置表单
                formRef.value.resetFields()
                // 判断权限是否为管理员
                
                if(res.data.permis && res.data.permis === 2) {
                  router.push("/admin");
                } 
                // 不是管理员, 当前在 admin页面
                else if(route.path === '/admin'){
                  router.push("/");
                }
                return true;
              } else {
                ElMessage.error("请求失败");
                return false;
              }
            })
          } 
          // 注册
          else {
            // 这里 form 需满足 user.ts 里的 interface User {username: string, password: string}
            userRegister(form).then(res => {
              ElMessage.success("注册成功")
              // 使用这个改变前提是， 传入的 state 是一个对象，而不是两个不一样的对象，
              // 如果传入的注册 state 对象 name 是 "register" ，那么如果改成 'login', 
              // 如果注册 state 对象 name 点击注册不会变，下次点击注册，就还会是显示登录界面
              // 如果不是一个，可以使用 const { name, state } = toRef(props.state); 用传入对象的属性，而不是对象
              props.state.name = LOGIN_STR
              return true;
            })
          }
        } else {
          console.log("error submit")
          return false;
        }
      })
    }
    
    const resetForm = () => {
      console.log(formRef)
      formRef.value.resetFields()
    }
    
    // 挂载完成，获取 sessionStorage 中用户信息 到 store
    onMounted(() => {
      store.commit('setUserInfoBySession');
    })
    
    // 离开页面时保存 store 信息到 sessionStorage
    window.addEventListener("beforeunload", () => {
      store.commit("addUserInfoToSession")
    })
    
    return {
      LOGIN_STR,
      REGISTER_STR,
      form,
      formRef,
      cancel,
      submit,
      rules,
      resetForm,
      verifyRef
    }
    
  }
})

</script>

<style>
</style>
